package com.mjk.manager.centerconf.type.impl;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import com.mjk.common.base.error.BizException;
import com.mjk.common.core.jdbc.datasource.CommonDataSourceAutoConf;
import com.mjk.common.core.jdbc.datasource.DynamicDataSource;
import com.mjk.common.core.jdbc.util.DataSourceUtil;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.util.MapUtils;
import com.mjk.common.util.PropertyUtil;
import com.mjk.manager.centerconf.type.RefreshInterface;
import com.mjk.manager.centerconf.type.RefreshType;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.google.common.base.Preconditions;
/**
 * 数据库连接刷新
 * @author jafek
 *
 */
@Component
public class DBRefreshImpl implements RefreshInterface,EnvironmentAware, BeeApplicationListener {
	private Environment environment;
	
	private ApplicationContext context;
	@Override
	public void refresh(AbstractApplicationContext context,Map<String,Object> refreshData,Map<String,Object> keys) {
		Map<String, Object> dbMap = MapUtils.containsKey(refreshData, RefreshType.DB.getKey());
		if(!CollectionUtils.isEmpty(dbMap)){
			DynamicDataSource source = context.getBean(DynamicDataSource.class);
			refreshDataSources(source,dbMap);		
		}		
	}
	public void refreshDataSources(DynamicDataSource source,Map<String,Object> keys){
		Map<Object, Object> targeDataSources = new HashMap<>();
		Map<String, String> driverMap = new HashMap<>();
		String prefix = "sharding.jdbc.datasource.";
		String dataSources;
		if(keys.containsKey("sharding.jdbc.datasource.names")){
			dataSources = keys.get("sharding.jdbc.datasource.names").toString();
		}else{
			dataSources = environment.getProperty(prefix + "names");
		}
		if (dataSources == null) {
			return ;
		}
		for (String each : dataSources.split(",")) {
			try {
				Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + each, Map.class);
				dataSourceProps.putAll(keys);
				Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
				DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(),
						dataSourceProps);
				driverMap.put(each, dataSourceProps.get("driver-class-name").toString());				
				targeDataSources.put(each, dataSource);
			} catch (final ReflectiveOperationException ex) {
				throw new BizException("Can't find datasource type!", ex);
			}
		}
		source.setTargetDataSources(targeDataSources);
		CommonDataSourceAutoConf conf = context.getBean(CommonDataSourceAutoConf.class);
		conf.setDriverMap(driverMap);
		source.afterPropertiesSet();
	}
	
	@Override
	public void doApplicationEvent(ContextRefreshedEvent event) {
		this.context = event.getApplicationContext();	
	}
	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}
}
